package net.scribblemedia.sqldsk.domain;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.TypedQuery;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooEntity(finders = { "findReportQuerysByNameAndDatabaseConfigEquals" })
public class ReportQuery {

    private static final int PAGINATION_NOT_REQUIRED = -1;

	private String name;

	@Column(length=4000)
    private String description;
    
    private boolean actionableRows;
    
    private boolean showArchivedRows;
    
    private String exportFilename;
    
    @Lob
    private String reportSql;

    @OneToMany
    private List<ReportRow> reportRows;

    @ManyToOne
    private DatabaseConfig databaseConfig;
    
    public List<ReportRow> getReportRows(int firstResult, boolean showArchivedRows, int maxResults) {
        EntityManager em = ReportQuery.entityManager();
        TypedQuery<ReportRow> q = em.createQuery("SELECT o FROM ReportRow AS o WHERE o.reportQuery = :reportQuery" + filterArchivedRowsClause(showArchivedRows), ReportRow.class);
        q.setParameter("reportQuery", this);
       
        if (firstResult != PAGINATION_NOT_REQUIRED) {
        	q.setFirstResult(firstResult);
        }
        
        if (maxResults != PAGINATION_NOT_REQUIRED) {
        	q.setMaxResults(maxResults);
        }
        
        return q.getResultList();
    }
    
    public Long countReportRows(boolean showArchivedRows) {
    	EntityManager em = ReportQuery.entityManager();
        TypedQuery<Long> q = em.createQuery("SELECT COUNT(o) FROM ReportRow AS o WHERE o.reportQuery = :reportQuery" + filterArchivedRowsClause(showArchivedRows), Long.class);
        q.setParameter("reportQuery", this);
        return q.getSingleResult();
    }

	private String filterArchivedRowsClause(boolean showArchivedRows) {
		return showArchivedRows ? "" : " AND o.archived = false";
	}
    
    public List<ReportRow> getReportRowsForCurrentArchiveState() {
    	return getReportRows(PAGINATION_NOT_REQUIRED, isShowArchivedRows(), PAGINATION_NOT_REQUIRED);
    }
    
    public void addReportRow(ReportRow reportRow) {
        createNewReportRowListIfNecessary();
        reportRows.add(reportRow);
        reportRow.setReportQuery(this);
    }

    public void removeAllReportRows() {
        createNewReportRowListIfNecessary();
        List<ReportRow> toRemove = new ArrayList<ReportRow>();
        toRemove.addAll(reportRows);
        for (ReportRow reportRow : toRemove) {
            removeReportRow(reportRow);
        }
    }

    public void removeReportRow(ReportRow reportRow) {
        createNewReportRowListIfNecessary();
        reportRows.remove(reportRow);
        reportRow.setReportQuery(null);
    }

    private void createNewReportRowListIfNecessary() {
        if (reportRows == null) {
            reportRows = new ArrayList<ReportRow>();
        }
    }

    public List<String> getColumnNames() {
        if (reportRows != null && !reportRows.isEmpty()) {
            List<ReportRowColumn> reportRowColumns = reportRows.get(0).getReportRowColumns();
            List<String> columnNames = new ArrayList<String>();
            for (ReportRowColumn column : reportRowColumns) {
                columnNames.add(column.getColumnName());
            }
            return columnNames;
        }
        return new ArrayList<String>();
    }
    
    public int getNonArchivedRowCount() {
    	int nonArchivedRowCount = 0;
    	
    	for (ReportRow reportRow : reportRows) {
    		if (!reportRow.isArchived()) {
    			nonArchivedRowCount++;
    		}
    	}
    	
    	return nonArchivedRowCount;
    }
}
